# -*- coding: utf-8 -*-

import logging
from copy import copy, deepcopy

from odoo import models, fields, api
from odoo.exceptions import UserError, ValidationError

from . cfprint_templates import outgoing_order_detail


_logger = logging.getLogger(__name__)


class BuliaoWeight(models.Model):
    _name = 'buliao.weight'

    name = fields.Integer(u'匹号', required=True)
    so_id = fields.Many2one('sale.order', u'销售订单', required=True)
    weight = fields.Float(u'匹重', required=True)
    done_date = fields.Datetime(u'完成时间', default=fields.Datetime.now)

    _sql_constraints = [
        ('name_unique',
         'UNIQUE(name, so_id)',
         u'提交失败，订单对应的匹号已经提交！'),
    ]


class SaleOrder(models.Model):
    _inherit = 'sale.order'

    # buliao_product_id = fields.Many2one(
    #     'product.product', string=u'布料', domain=[('categ_id.name', '=', u'客户布料')], required=True
    # )
    buliao_color = fields.Char(string=u'颜色', readonly=True, states={'draft': [('readonly', False)]})
    buliao_type = fields.Char(string=u'品名', readonly=True, states={'draft': [('readonly', False)]})
    buliao_width = fields.Float(string=u'幅宽', readonly=True, states={'draft': [('readonly', False)]})
    buliao_g_weight = fields.Float(string=u'克重', readonly=True, states={'draft': [('readonly', False)]})
    buliao_net_weight = fields.Float(string=u'净重', readonly=True, compute='_compute_net_weight', store=True)
    buliao_weight = fields.Float(string=u'毛重', readonly=True, states={'draft': [('readonly', False)]})
    buliao_qty = fields.Integer(string=u'匹数', readonly=True, states={'draft': [('readonly', False)]}, default=1)
    customer_origin = fields.Char(string=u'缸号', readonly=True, states={'draft': [('readonly', False)]})
    buliao_note = fields.Char(string=u'备注')
    #plan_id = fields.Many2one('buliao.produce.plan', u'生产计划单')
    line_names = fields.Char(u'工艺要求', compute='_compute_line_names')
    produce_state = fields.Selection([
        ('draft', u'未排产'),
        ('plan', u'已排产'),
        ('running', u'生产中'),
        ('done', u'生产完毕')
        ], string=u'生产状态', readonly=True, copy=False, index=True, default='draft')
    buliao_weight_ids = fields.One2many('buliao.weight', 'so_id', u'匹重')
    buliao_unit_price = fields.Monetary(u'单价', help=u'每匹布的单价', store=True, compute='_compute_buliao_unit_price')
    incoming_order_id = fields.Many2one('buliao.incoming.order', u'入库单')
    produce_done_date = fields.Datetime(u'生产完成时间')

    @api.constrains('partner_id')
    def _check_partner_id(self):
        if self.incoming_order_id and self.incoming_order_id.partner_id != self.partner_id:
            raise ValidationError(u'入库单客户与销售订单客户不一致！单号: %s' % self.name)

    @api.onchange('partner_id')
    def onchange_partner_id_diff(self):
        warning = {}
        if self.incoming_order_id and self.incoming_order_id.partner_id != self.partner_id:
            # raise UserError(u'入库单与销售单的客户需要一致！')
            warning = {
                'title': u'注意',
                'message': u'销售单的客户需要与入库单的客户一致！'
            }
            # self.partner_id = self.incoming_order_id.partner_id
        res = {}
        if warning:
            res['warning'] = warning
        return res

    @api.onchange('buliao_qty')
    def onchange_buliao_qty(self):
        if self.buliao_qty <= 0:
            raise UserError(u'匹数必须要大于0')
        # 按 净重或者毛重 计算价格
        # self.order_line.update({'product_uom_qty': self.buliao_qty})

    @api.one
    @api.depends('buliao_weight_ids.weight')
    def _compute_net_weight(self):
        buliao_net_weight = 0.0
        for w in self.buliao_weight_ids:
            buliao_net_weight += w.weight
        self.buliao_net_weight = buliao_net_weight

    @api.one
    @api.depends('order_line')
    def _compute_buliao_unit_price(self):
        buliao_unit_price = 0
        for line in self.order_line:
            buliao_unit_price += line.price_unit
        self.buliao_unit_price = buliao_unit_price

    @api.multi
    @api.depends('order_line.name')
    def _compute_line_names(self):
        for rec in self:
            names = rec.mapped('order_line.product_id.name')
            rec.line_names = ','.join(names)

    # 弃用
    # def generate_produce_plan(self):
    #     recs = self
    #     partner = recs.mapped('partner_id')
    #     if len(partner) > 1:
    #         raise UserError(u'生成的计划单中只能出现一个客户，请重新选择销售订单。')
    #     if recs.filtered(lambda r: r.state != 'sale'):
    #         raise UserError(u'只有确认的销售订单才能生成计划单。')
    #     if recs.filtered(lambda r: r.produce_state != 'draft'):
    #         raise UserError(u'销售订单的生产状态错误,只有未排产的销售订单才能生成计划单。')
    #     assigned_so = recs.filtered(lambda r: r.plan_id)
    #     if assigned_so:
    #         so_ref = assigned_so.mapped('name')
    #         raise UserError(u'%s 已经分配计划单' % ','.join(so_ref))
    #     vals = {'partner_id': partner.ids[0]}
    #     plan = self.env['buliao.produce.plan'].create(vals)
    #     recs.update({'plan_id': plan})
    #     return True

    # 测试
    # @api.multi
    # def action_change_state(self):
    #     if self.produce_state == 'draft':
    #         self.produce_state = 'running'
    #     elif self.produce_state == 'running':
    #         self.produce_state = 'done'
    #     else:
    #         self.produce_state = 'draft'

    def change_line_qty(self):
        # 当so生产状态变为done时，根据结算方法改变订单行的数量
        product_uom_qty = 0
        if self.incoming_order_id.compute_method == 'weight':
            product_uom_qty = self.buliao_weight
        elif self.incoming_order_id.compute_method == 'net_weight':
            product_uom_qty = self.buliao_net_weight
        self.order_line.update({'product_uom_qty': product_uom_qty})

    @api.multi
    def action_produce_done(self):
        done_date = fields.Datetime.now()
        self.produce_state = 'done'
        self.produce_done_date = done_date
        self.change_line_qty()
        return True

    @api.multi
    def generate_buliao_weight(self, weight, name):
        weight_obj = self.env['buliao.weight']
        done_date = fields.Datetime.now()
        weight = float(weight)
        weight_obj.create({
            'name': int(name),
            'so_id': self.id,
            'weight': weight,
            'done_date': done_date
        })

        if len(self.buliao_weight_ids) == 1:
            self.produce_state = 'running'
        if len(self.buliao_weight_ids) == self.buliao_qty:
            self.action_produce_done()
        res = {
            'number': name,
            'done_date': done_date,
            'weight': weight,
            'partner': self.partner_id.name,
            'buliao_type': self.buliao_type or u'空',
            'customer_origin': self.customer_origin or u'空',
            'buliao_width': self.buliao_width or 0,
            'buliao_g_weight': self.buliao_g_weight or 0,
        }
        return res

    def print_style(self):
        # 实现水平填充
        # 如果需要实现垂直填充，首先确定有多少列，然后判断weight总数是否超过列数
        groups = []
        group = []
        for w in self.buliao_weight_ids:
            group.append((w.name, w.weight))
            if len(group) == 3:
                groups.append(copy(group))
                group = []
        if group:
            groups.append(group)
        return groups

    # @api.multi
    # def action_print_weight_detail(self):
    #     self.ensure_one()
    #     return {
    #         'type': 'ir.actions.client',
    #         'tag': 'open_report',
    #         'params': {
    #             'active_id': self.id,
    #             'report_name': 'lmch_buliao.weight_detail_report',
    #             'report_type': 'html'
    #         }
    #     }

    @api.model
    def get_wait_so(self, cur_offset, cur_so_id):
        # 单个rpc使用model修饰，多个使用multi,传入ids
        wait_so = self.search(
            [('produce_state', 'in', ['plan', 'running']), ('id', '!=', cur_so_id)],
            offset=cur_offset,
            limit=5
        )
        res = wait_so.mapped(lambda r: [
            r.id,
            r.name or u'空',
            r.partner_id.name or u'空',
            r.customer_origin or u'空',
            r.buliao_type or u'空',
            r.incoming_order_id.plan_name or u'空',
            u'部分生产' if r.produce_state == 'running' else u'等待生产'
        ])
        return res

    @api.model
    def get_done_weights(self, cur_offset, cur_modify_weight_id):
        weight_obj = self.env['buliao.weight']
        weights = weight_obj.search(
            [('id', '!=', cur_modify_weight_id)], offset=cur_offset, limit=5, order="done_date desc"
        )
        res = weights.mapped(lambda r: [
            r.id,
            r.so_id.name or u'空',
            r.so_id.partner_id.name or u'空',
            r.so_id.customer_origin or u'空',
            r.so_id.buliao_type or u'空',
            r.so_id.incoming_order_id.plan_name or u'空',
            r.done_date,
            r.weight,
            r.name
        ])
        return res

    @api.model
    def get_modify_weight_info(self, cur_modify_weight_id):
        weight_obj = self.env['buliao.weight']
        modify_weight = weight_obj.browse(cur_modify_weight_id)
        res = {
            'id': modify_weight.id,
            'so_name': modify_weight.so_id.name or u'空',
            'weight': modify_weight.weight
        }
        return res

    @api.model
    def modify_weight(self, new_weight, cur_modify_weight_id):
        weight_obj = self.env['buliao.weight']
        modify_weight = weight_obj.browse(cur_modify_weight_id)
        modify_weight.weight = new_weight
        so = modify_weight.so_id
        res = {
            'number': modify_weight.name,
            'done_date': modify_weight.done_date,
            'weight': new_weight or 0,
            'partner': so.partner_id.name,
            'buliao_type': so.buliao_type or u'空',
            'customer_origin': so.customer_origin or u'空',
            'buliao_width': so.buliao_width or 0,
            'buliao_g_weight': so.buliao_g_weight or 0,
        }
        return res

    @api.multi
    def get_so_qty(self):
        # 获取总匹数与当前匹数
        res = {}
        if len(self) == 0:
            res['warning'] = u'未找到对应订单！'
        else:
            if self.produce_state in ['plan', 'running']:
                res = {
                    'id': self.id,
                    'buliao_qty': self.buliao_qty,
                    'cur_qty': len(self.buliao_weight_ids)+1 if self.buliao_weight_ids else 1,
                    'name': self.name,
                    'partner_name': self.partner_id.name
                }
            else:
                res = {'warning': u'订单状态发生改变:%s' % self.produce_state}
        return res

    @api.model
    def get_so_qty_byname(self, so_name):
        so_name = so_name.upper()
        res = {}
        if len(self) > 1:
            res['warning'] = u'订单名称重复！'
        else:
            so = self.search([('name', '=', so_name)])
            res = so.get_so_qty()
        return res

    def _prepare_outgoing_order_detail_print_data(self):
        printer_name = self.env['ir.values'].get_default('buliao.config.settings', 'outgoing_order_detail_printer')
        rows = self.env['ir.values'].get_default('buliao.config.settings', 'outgoing_order_detail_rows')
        # 这里引入的是一个全局的字典，需要先clone一下。不clone则批量打印码单时会打印同一个字典
        # 因为字典的值为字典和数组，需要使用深度拷贝
        _reportData = deepcopy(outgoing_order_detail)
        _reportData['Printer'] = printer_name

        table1_data = {
          "buliao_note": self.buliao_note or '',
          "partner": self.partner_id.name,
          "buliao_type": self.buliao_type or '',
          "customer_origin": self.customer_origin or '',
          "buliao_width": self.buliao_width or 0.0,
          "buliao_g_weight": self.buliao_g_weight or 0.0,
          "buliao_qty": self.buliao_qty or 0,
          "so_name": self.name,
          "buliao_weight": self.buliao_weight,
          "buliao_net_weight": self.buliao_net_weight
        }
        _reportData['Tables'][0]['Data'] = [table1_data]

        table2_empty_data = {'buliao_name': '', 'buliao_weight': ''}
        table2_datas = []
        for weight in self.buliao_weight_ids:
            table2_datas.append({'buliao_name': weight.name, 'buliao_weight': weight.weight})
        dif = rows - len(self.buliao_weight_ids)
        if dif > 0:
            map(lambda r: table2_datas.append(table2_empty_data), xrange(dif))
        _reportData['Tables'][1]['Data'] = table2_datas

        return _reportData

    @api.multi
    def action_cfprint(self):
        # 支持从入库单批量打印与单独打印
        _reportDatas = []
        for so in self:
            data = so._prepare_outgoing_order_detail_print_data()
            _reportDatas.append(data)
        return {
            'type': 'ir.actions.client',
            'tag': 'cfprint_report',
            'params': {
                '_reportDatas': _reportDatas
            }
        }




